package scala.tools.eclipse.maven.core;

import org.devzuz.q.maven.project.configuration.IProjectConfigurationParticipant;
import org.devzuz.q.maven.embedder.{IMavenProject,IMavenArtifact};
import org.apache.maven.model.Plugin;
import org.eclipse.core.runtime.IProgressMonitor;
import scala.collection.jcl.Conversions._;
import org.eclipse.jdt.core.{JavaCore,IClasspathEntry}
import org.eclipse.core.resources.IProject;
import scala.tools.eclipse.util.Matching._;
/** This class will add a scala nature ot a maven project*/
class ImportProjectPostprocessor extends IProjectConfigurationParticipant {
  
  val NATURE_ID = "ch.epfl.lamp.sdt.core.scalanature"; //TODO - Pull this from plugin...
  val SCALA_PLUGIN_VERSION="2.7.1"
  
  val LIRBARY_ID = "scala-library";
  val LIBRARY_GROUP  = "org.scala-lang";
  val MAVEN_PLUGIN_ID = "scala-plugin";
  val MAVEN_PLUGIN_GROUP = "org.scala-tools";
  
  /** Processes a new maven project and will add Scala Nature if needed */
  def process( mavenProject : IMavenProject ,  monitor : IProgressMonitor ) : Unit = {
    MavenPlugin.plugin.checkedDo {
      setupProject(mavenProject, monitor);
    }
  }
  
   /**
    * Sets up a maven project for Scala development
    */
   private def setupProject( project : IMavenProject, monitor : IProgressMonitor ) : Unit = {
     System.err.println("TODO - Set up Scala");
     
     if(!project.getProject.hasNature(NATURE_ID) && needsScalaNature(project)) {
       var natures = project.getProject.getDescription.getNatureIds
       var newNatures = new Array[String](natures.length+1);
       for(i <- 0 until natures.length) {
         newNatures(i) = natures(i);
       }
       newNatures(natures.length) = NATURE_ID;
       
       System.err.println("Adding natures: " + newNatures.deepToString);
       var description = project.getProject.getDescription;
       description.setNatureIds(newNatures);
       project.getProject.setDescription(description, monitor);
       
       System.err.println("Adding source paths: " + newNatures.deepToString);
       addSourcePaths(project, monitor);
     }
   }
   /** Adds the source paths defined by Scala Plguin to the project */
   private def addSourcePaths(project : IMavenProject, monitor : IProgressMonitor) : Unit = {
     import scala.collection.jcl.Conversions._;
     var sourcePath = getAdditionalSourcePaths(project);    
     if(!sourcePath.isEmpty) {
	     project.getProject match {
	       case JavaProject(project) => 
	         val newClassPath = sourcePath ++ project.getRawClasspath;
	         project.setRawClasspath(newClassPath.toArray, monitor);
	     }
     }
   }
   
   /** Pulls source paths that should be added to the project */
   private def getAdditionalSourcePaths(project : IMavenProject) : List[IClasspathEntry] = {
     //A few classes only used in this plugin

     import org.w3c.dom._;
     import scala.tools.eclipse.util.XmlUtil._;    
     /** This method pulls the classpath from the Maven plugin */
     def getSourcePathsFromConfiguration(project : IMavenProject, configuration : Element) : List[IClasspathEntry] = {
       /** Creates a Source entry from a Dom Node where the text content is a project-local directory */
       def makeSourceEntryFromConfigNode(node : org.w3c.dom.Node) = {
         node.normalize
         val folder = project.getProject.getFolder(node.getTextContent)
         //TODO - Check
         JavaCore.newSourceEntry(folder.getFullPath)
       }
       
       var toReturn : List[IClasspathEntry] = List()
       for(node <- configuration.getElementsByTagName("sourceDir")) {
         toReturn = makeSourceEntryFromConfigNode(node) :: toReturn
       }
       for(node <- configuration.getElementsByTagName("testDir")) {
         toReturn = makeSourceEntryFromConfigNode(node) :: toReturn;
       }
       toReturn
     }
     
     for(plugin <- getScalaPlugin(project)) {
       plugin.getConfiguration match {
           case element : Element => return getSourcePathsFromConfiguration(project, element)
       }
     }     
     return List()
   }
   /** Tests to see if something is a scala plugin */
   private def isScalaPlugin(plugin : Plugin) : Boolean = (plugin.getArtifactId equals MAVEN_PLUGIN_ID) && (plugin.getGroupId equals MAVEN_PLUGIN_GROUP)
   /** Retreives the scala plugin from a project*/
   private def getScalaPlugin(project : IMavenProject) = {
     (for{
       plugin <- project.getBuildPlugins 
       if isScalaPlugin(plugin)
     } yield plugin).firstOption
   }
   
   /** Returns true if the project needs a scala nature to build */
   private def needsScalaNature(project : IMavenProject) : Boolean = getScalaPlugin(project).isDefined
   
  
}
